#include "cCityGuardian.h"
#include "cScene.h"

cCityGuardian::cCityGuardian(void)
{
	//Por defecto se comporta como cualquier otro NPC
	SetTextCoords(160, 864);	//Ponemos que se pinte con la textura de guardia.
	guardianPath = NULL;		//Copiamos la ruta
	pathIndex = 0;
	routePointsNumber = 0;
	routeDirection = true;
	isEnemy = false;
}

cCityGuardian::~cCityGuardian(void)
{
	if (guardianPath) delete[] guardianPath;
	guardianPath = NULL;
}

void cCityGuardian::StartRoute(cScene *scene, int numPoints, int startPoint, cPoint2D *routePoints, bool clockwise)
{
	if (guardianPath) delete[] guardianPath;
	guardianPath = NULL;
	guardianPath = new cPoint2D[numPoints];

	//Copiamos la ruta
	for(int i = 0; i < numPoints; ++i)
	{
		guardianPath[i] = cPoint2D(routePoints[i].X(), routePoints[i].Y() );
	}
	routePointsNumber = numPoints;
	routeDirection = clockwise;
	pathIndex = startPoint;

	if(routeDirection)
	{
		++pathIndex;
		pathIndex %= routePointsNumber;
	}
	else
	{
		if(pathIndex == 0) pathIndex = routePointsNumber;
		--pathIndex;
	}

	path.Make(scene, cx, cy, guardianPath[pathIndex].X(), guardianPath[pathIndex].Y() );
}

void cCityGuardian::BlockCells(cScene *scene)
{
	int *walkabilityMap = NULL;

	scene->GetWalkabilityMap(&walkabilityMap);

	--walkabilityMap[cy*scene->GetSceneArea() + cx];
	if(cy-1 >= 0 && cx-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx-1] <= 0)
		--walkabilityMap[(cy-1)*scene->GetSceneArea() + cx-1];
	if(cx-1 >= 0 && walkabilityMap[cy*scene->GetSceneArea() + cx-1] <= 0)
		--walkabilityMap[cy*scene->GetSceneArea() + cx-1];
	if(cy+1 < scene->GetSceneArea() && cx-1 >= 0 && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx-1] <= 0)
		--walkabilityMap[(cy+1)*scene->GetSceneArea() + cx-1];
	if(cy+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx] <= 0)
		--walkabilityMap[(cy+1)*scene->GetSceneArea() + cx];
	if(cy+1 < scene->GetSceneArea() && cx+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx+1] <= 0)
		--walkabilityMap[(cy+1)*scene->GetSceneArea() + cx+1];
	if(cx+1 < scene->GetSceneArea() && walkabilityMap[cy*scene->GetSceneArea() + cx+1] <= 0)
		--walkabilityMap[cy*scene->GetSceneArea() + cx+1];
	if(cy-1 >= 0 && cx+1 < scene->GetSceneArea() && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx+1] <= 0)
		--walkabilityMap[(cy-1)*scene->GetSceneArea() + cx+1];
	if(cy-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx] <= 0)
		--walkabilityMap[(cy-1)*scene->GetSceneArea() + cx];
}

void cCityGuardian::UnBlockCells(cScene *scene)
{
	int *walkabilityMap = NULL;

	scene->GetWalkabilityMap(&walkabilityMap);

	++walkabilityMap[cy*scene->GetSceneArea() + cx];
	if(cy-1 >= 0 && cx-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx-1] < 0)
		++walkabilityMap[(cy-1)*scene->GetSceneArea() + cx-1];
	if(cx-1 >= 0 && walkabilityMap[cy*scene->GetSceneArea() + cx-1] < 0)
		++walkabilityMap[cy*scene->GetSceneArea() + cx-1];
	if(cy+1 < scene->GetSceneArea() && cx-1 >= 0 && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx-1] < 0)
		++walkabilityMap[(cy+1)*scene->GetSceneArea() + cx-1];
	if(cy+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx] < 0)
		++walkabilityMap[(cy+1)*scene->GetSceneArea() + cx];
	if(cy+1 < scene->GetSceneArea() && cx+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx+1] < 0)
		++walkabilityMap[(cy+1)*scene->GetSceneArea() + cx+1];
	if(cx+1 < scene->GetSceneArea() && walkabilityMap[cy*scene->GetSceneArea() + cx+1] < 0)
		++walkabilityMap[cy*scene->GetSceneArea() + cx+1];
	if(cy-1 >= 0 && cx+1 < scene->GetSceneArea() && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx+1] < 0)
		++walkabilityMap[(cy-1)*scene->GetSceneArea() + cx+1];
	if(cy-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx] < 0)
		++walkabilityMap[(cy-1)*scene->GetSceneArea() + cx];
}

void cCityGuardian::Update(cScene *scene)
{
	bool willCollide = false;
	int cxdest, cydest, move;
	int *walkabilityMap = NULL;

	scene->GetWalkabilityMap(&walkabilityMap);

	if(!path.IsDone() )
	{
		switch(path.Faced() )
		{
			case N:
				if(cy-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx] < 0)
					willCollide = true;
				break;
			case S:
				if(cy+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx] < 0)
					willCollide = true;
				break;
			case E:
				if(cx+1 < scene->GetSceneArea() && walkabilityMap[cy*scene->GetSceneArea() + cx+1] < 0)
					willCollide = true;
				break;
			case O:
				if(cx-1 >= 0 && walkabilityMap[cy*scene->GetSceneArea() + cx-1] < 0)
					willCollide = true;
				break;
			case NE:
				if(cx+1 < scene->GetSceneArea() && cy-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx+1] < 0)
					willCollide = true;
				break;
			case NO:
				if(cx-1 >= 0 && cy-1 >= 0 && walkabilityMap[(cy-1)*scene->GetSceneArea() + cx-1] < 0)
					willCollide = true;
				break;
			case SE:
				if(cx+1 < scene->GetSceneArea() && cy+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx+1] < 0)
					willCollide = true;
				break;
			case SO:
				if(cx-1 >= 0 && cy+1 < scene->GetSceneArea() && walkabilityMap[(cy+1)*scene->GetSceneArea() + cx-1] < 0)
					willCollide = true;
				break;
			default:
				return;
		}

		if(willCollide)
		{
			path.GetDestinationCell(&cxdest, &cydest);
			path.ReMake(scene, cxdest, cydest);
		}

		move = path.NextStep(&x, &y, &cx, &cy);

		if(move == ARRIVE)
		{
			path.Done();
			animSeq = 0;
		}
	}
	else
	{
		if(routeDirection)
		{
			++pathIndex;
			pathIndex %= routePointsNumber;
		}
		else
		{
			if(pathIndex == 0) pathIndex = routePointsNumber;
			--pathIndex;
		}

		// Create a new piece of route
		path.Make(scene, cx, cy, guardianPath[pathIndex].X(), guardianPath[pathIndex].Y() );
	}
}